﻿/*
    类 说 明：业务逻辑类，封装了数据表相关基本操作
	生成时间：2020/10/1 11:26:12
	生成工具：Kalman Studio
*/

using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Threading.Tasks;

using Kalman;
using Newtonsoft.Json.Linq;
using Kalman.Extensions;
using TencentCloud.Ame.V20190916.Models;
using TencentCloud.Tsf.V20180326.Models;
using Google.Protobuf.WellKnownTypes;
using AliyunOss;
using TencentCloud.Cpdp.V20190820.Models;
using TencentCloud.Ocr.V20181119.Models;

namespace QuDao
{
    /// <summary>
    /// 数据表base_goods关联的业务对象，处理该表相关的业务逻辑
    /// </summary>
    public sealed partial class GoodsBO : SingletonBase<GoodsBO>
    {
        readonly IFreeSql fsql;
        readonly AliyunOssClient oss;
        readonly AppSettings appSettings;
        public GoodsBO() : base()
        {
            oss = new AliyunOssClient();
            fsql = ServiceLocator.Instance.GetRequiredService<IFreeSql>();
            appSettings = AppConfig.Instance.GetSection<AppSettings>("AppSettings");
        }

        /// <summary>
        /// 获取商品
        /// </summary>
        /// <param name="id">主键ID的值</param>
        /// <returns></returns>
        public T GetItem<T>(int id)
        {
            var item = fsql.Select<Goods>().Where(a => a.GoodsID == id).ToOne<T>();
            return item;
        }

        /// <summary>
        /// 获取商品数据列表
        /// </summary>
        /// <returns></returns>
        public List<T> GetList<T>(int[] ids)
        {
            var list = fsql.Select<Goods>().Where(a => ids.Contains(a.GoodsID)).ToList<T>();
            return list;
        }

        /// <summary>
        /// 后台查询数据（分页）
        /// </summary>
        /// <param name="req">分页查询请求对象</param>
        public PagingResult<T> Query<T>(PagingRequest req, int tid = 0)
        {
            var select = fsql.Select<Goods>().WhereIf(tid > 0, a => a.TID == tid);
            foreach (var item in req.FilterItems)
            {
                switch (item.Field)
                {
                    case "GoodsID":
                        select.Where(a => a.GoodsID == int.Parse(item.Value));
                        break;
                    case "GoodsName":
                        select.Where(a => a.GoodsName.Contains(item.Value));
                        break;
                    default:
                        break;
                }
            }

            if (!string.IsNullOrEmpty(req.SortExp))
            {
                select.OrderBy(req.SortExp).OrderByDescending(a => a.GoodsID);//自定义排序
            }
            else
            {
                select.OrderByDescending(a => a.GoodsID);//默认排序
            }

            var sql = select.ToSql();

            var list = select.Count(out var total).Page(req.PageIndex, req.PageSize).ToList<T>();
            
            return new PagingResult<T>
            {
                PageIndex = req.PageIndex,
                PageSize = req.PageSize,
                Data = list,
                Total = (int)total
            };
        }

        public PagingResult<Goods> Query(PagingRequest req, int tid = 0)
        {
            var result = Query<Goods>(req, tid);
            var list = result.Data;
            var tenant = TenantBO.Instance.GetItem(tid);

            foreach (var item in list)
            {
                if(item.IsSpecial) continue; //特价不用按折扣计算各级会员价
                item.MAPrice = decimal.Round(item.MarketPrice * tenant.MADiscount, 2);
                item.MBPrice = decimal.Round(item.MarketPrice * tenant.MBDiscount, 2);
                item.MCPrice = decimal.Round(item.MarketPrice * tenant.MCDiscount, 2);
                item.Commission = decimal.Round(item.MarketPrice * tenant.CommissionRatio, 2);
            }

            return result;
        }

        public Goods GetItem(int id)
        {
            return GetItem<Goods>(id);
        }

        /// <summary>
        /// 获取商品详情
        /// </summary>
        public GoodsDetailsDto GetDetails(int goodsID)
        {
            var goods = GetItem<GoodsDetailsDto>(goodsID) ?? throw new AppException($"商品不存在：{goodsID}");
            var tenant = TenantBO.Instance.GetItem(goods.TID);

            if (!goods.IsSpecial)
            {
                goods.MAPrice = decimal.Round(goods.MarketPrice * tenant.MADiscount, 2);
                goods.MBPrice = decimal.Round(goods.MarketPrice * tenant.MBDiscount, 2);
                goods.MCPrice = decimal.Round(goods.MarketPrice * tenant.MCDiscount, 2);
                goods.Commission = decimal.Round(goods.MarketPrice * tenant.CommissionRatio, 2);
            }

            goods.AlbumList = AlbumBO.Instance.GetListByGoods(goodsID);
            goods.VideoList = VideoBO.Instance.GetListByGoods(goodsID);
            return goods;
        }

        /// <summary>
        /// 获取租户商品列表
        /// </summary>
        /// <param name="tid">租户ID</param>
        /// <param name="userType">用户类型：A|B|C</param>
        /// <param name="status">状态：1-销售中，2-已下架</param>
        /// <param name="pageIndex">页索引，从1开始</param>
        /// <param name="pageSize">每页记录数，默认10</param>
        public IEnumerable<GoodsDto> GetList(int tid, string userType, int categoryID, int pageIndex = 1, int pageSize = 10)
        {
            var ut = userType switch
            {
                "A" => 1,
                "B" => 2,
                "C" => 4,
                _ => 7
            };

            var list = fsql.Select<Goods>()
                .Where(a => a.TID == tid && a.Status == 1 && (a.SalesRange & ut) > 0)
                .WhereIf(categoryID > 0, a => a.CategoryID == categoryID)
                .OrderByDescending(a => a.SortFlag)
                .OrderByDescending(a => a.GoodsID)
                .Page(pageIndex, pageSize)
                .ToList<GoodsDto>();
            var tenant = TenantBO.Instance.GetItem(tid);

            foreach (var item in list)
            {
                if(item.IsSpecial) continue; //特价不用按折扣计算各级会员价
                item.MAPrice = decimal.Round(item.MarketPrice * tenant.MADiscount, 2);
                item.MBPrice = decimal.Round(item.MarketPrice * tenant.MBDiscount, 2);
                item.MCPrice = decimal.Round(item.MarketPrice * tenant.MCDiscount, 2);
                item.Commission = decimal.Round(item.MarketPrice * tenant.CommissionRatio, 2);
            }

            return list;
        }

        /// <summary>
        /// 新增商品
        /// </summary>
        public int Add(GoodsAddDto dto)
        {
            if (dto.GoodsName.IsNullOrEmpty()) throw new AppException("商品名称不能为空");
            if (dto.CostPrice > dto.MarketPrice) throw new AppException("成本价不能大于市场价");

            if (dto.IsSpecial)
            {
                if (dto.MAPrice > dto.MBPrice) throw new AppException("A级会员价不能大于B级会员价");
                if (dto.MBPrice > dto.MCPrice) throw new AppException("B级会员价不能大于C级会员价");
                //if (dto.CostPrice < dto.MCPrice) throw new AppException("成本价不能小于C级会员价");
                if (dto.CostPrice + dto.Commission > dto.MAPrice) throw new AppException("成本价加上业绩提成不能大于A级会员价");
            }

            //var tenant = TenantBO.Instance.GetItem(dto.TID) ?? throw new AppException($"无效的租户：{dto.TID}");
            var category = CategoryBO.Instance.GetItem(dto.CategoryID);
            var goods = new Goods
            {
                TID = dto.TID,
                GoodsName = dto.GoodsName,
                CategoryID = dto.CategoryID,
                CategoryName = category.CategoryName,
                ImageUrl = dto.ImageUrl,
                MarketPrice = dto.MarketPrice,
                CostPrice = dto.CostPrice,
                IsSpecial = dto.IsSpecial,
                SalesRange = dto.SalesRange,
                SortFlag = dto.SortFlag,
                Status = dto.Status,
                CreateTime = DateTime.Now,
                ModifyTime = DateTime.Now,
                //Memo = dto.Memo
            };

            if (dto.IsSpecial)
            {
                goods.MAPrice = dto.MAPrice;
                goods.MBPrice = dto.MBPrice;
                goods.MCPrice = dto.MCPrice;
                goods.Commission = dto.Commission;
            }

            goods.GoodsID = (int)fsql.Insert(goods).ExecuteIdentity();
            return goods.GoodsID;
        }

        /// <summary>
        /// 修改商品
        /// </summary>
        public int Modify(GoodsModifyDto dto)
        {
            var item = GetItem<Goods>(dto.GoodsID) ?? throw new AppException($"商品不存在：{dto.GoodsID}");

            if (dto.GoodsName.IsNullOrEmpty()) throw new AppException("商品名称不能为空");
            if (dto.CostPrice > dto.MarketPrice) throw new AppException("成本价不能大于市场价");

            if (dto.IsSpecial)
            {
                if (dto.MAPrice > dto.MBPrice) throw new AppException("A级会员价不能大于B级会员价");
                if (dto.MBPrice > dto.MCPrice) throw new AppException("B级会员价不能大于C级会员价");
                //if (dto.CostPrice < dto.MCPrice) throw new AppException("成本价不能小于C级会员价");
                if (dto.CostPrice + dto.Commission > dto.MAPrice) throw new AppException("成本价加上业绩提成不能大于A级会员价");
            }

            var update = fsql.Update<Goods>(dto.GoodsID).Set(a => a.ModifyTime, DateTime.Now);

            if (dto.GoodsName != item.GoodsName) update.Set(a => a.GoodsName, dto.GoodsName);
            if (!string.IsNullOrEmpty(dto.ImageUrl) && dto.ImageUrl != item.ImageUrl) update.Set(a => a.ImageUrl, dto.ImageUrl);
            if (dto.CostPrice != item.CostPrice) update.Set(a => a.CostPrice, dto.CostPrice);
            if (dto.MarketPrice != item.MarketPrice) update.Set(a => a.MarketPrice, dto.MarketPrice);
            if (dto.IsSpecial != item.IsSpecial) update.Set(a => a.IsSpecial, dto.IsSpecial);
            if (dto.MAPrice != item.MAPrice) update.Set(a => a.MAPrice, dto.MAPrice);
            if (dto.MBPrice != item.MBPrice) update.Set(a => a.MBPrice, dto.MBPrice);
            if (dto.MCPrice != item.MCPrice) update.Set(a => a.MCPrice, dto.MCPrice);
            if (dto.Commission != item.Commission) update.Set(a => a.Commission, dto.Commission);
            if (dto.SalesRange != item.SalesRange) update.Set(a => a.SalesRange, dto.SalesRange);
            if (dto.SortFlag != item.SortFlag) update.Set(a => a.SortFlag, dto.SortFlag);
            if (dto.Status != item.Status) update.Set(a => a.Status, dto.Status);

            if (dto.CategoryID != item.CategoryID)
            {
                var category = CategoryBO.Instance.GetItem(dto.CategoryID);
                update.Set(a => a.CategoryID, dto.CategoryID).Set(a => a.CategoryName, category.CategoryName);
            }


            return update.ExecuteAffrows();
        }

        /// <summary>
        /// 商品上架
        /// </summary>
        public int SetUp(int id)
        {
            var goods = GetItem(id);
            if (goods == null) throw new AppException("商品不存在");
            if (goods.Status == 1) return 0;

            return fsql.Update<Goods>(id).Set(a => a.Status, 1).ExecuteAffrows();
        }

        /// <summary>
        /// 商品下架
        /// </summary>
        public int SetDown(int id)
        {
            var goods = GetItem(id);
            if (goods == null) throw new AppException("商品不存在");
            if (goods.Status == 2) return 0;

            return fsql.Update<Goods>(id).Set(a => a.Status, 2).ExecuteAffrows();
        }

        /// <summary>
        /// 删除商品数据
        /// </summary>
        public void Delete(int id, bool isFromDB = true)
        {
            var goods = GetItem(id);
            if (goods == null) return;

            if (goods.SalesNum > 0 && isFromDB == false) //逻辑删除
            {
                fsql.Update<Goods>(id).Set(a => a.Status, -1).ExecuteAffrows();
            }
            else
            {
                fsql.Delete<Goods>(id).ExecuteAffrows();
            }
        }


    }
}
